﻿using System;
using System.Collections.Generic;
using System.Linq;
using Colligate;

namespace OrgDataSource
{
// ReSharper disable InconsistentNaming
    public class RoleDS : IOrgDS
// ReSharper restore InconsistentNaming
    {
        #region\\delete
        public int DeleteTaskData(OUDataInfo userInfo, string dataGuid, string dataType, orgEntities context)
        {
            switch (dataType.ToLower())
            {
                case "rolemember": return DeleteRoleMember(dataGuid, context);
                case "roleauthority": return DeleteRoleAuthority(dataGuid, context);
                default: throw new Exception("RoleDS无法处理该" + dataType + "的数据");
            }
        }

        private static int DeleteRoleMember(string dataGuid, orgEntities context)
        {
            System.Data.Common.DbTransaction tran = null;
            try
            {
                context.Connection.Open();
                tran = context.Connection.BeginTransaction();
                var rolemember = context.Role.FirstOrDefault(cc => cc.Guid == dataGuid);
                var tempList = rolemember.RoleMember.ToList();
                foreach (var item in tempList)
                    context.RoleMember.DeleteObject(item);
                context.DeleteObject(rolemember);
                var result = context.SaveChanges();
                tran.Commit();
                return result == 1 ? 0 : 1;
            }
            catch
            {
                if (tran != null) tran.Rollback();
                throw new Exception("删除数据标识为：" + dataGuid + "的RoleMember数据时出错！");
            }
            finally
            {
                if (context != null && context.Connection.State != System.Data.ConnectionState.Closed)
                    context.Connection.Close();
            }
        }
        private static int DeleteRoleAuthority(string dataGuid, orgEntities context)
        {
            try
            {
                var roleauthority = context.Role.FirstOrDefault(cc => cc.Guid == dataGuid);
                context.DeleteObject(roleauthority);
                var result = context.SaveChanges();
                return result == 1 ? 0 : 1;
            }
            catch
            {
                throw new Exception("删除数据标识为：" + dataGuid + "的RoleAuthority数据时出错！");
            }
        }
        #endregion
        #region\\get
        public System.Xml.XmlNode GetTaskData(OUDataInfo userInfo, string dataGuid, string dataType, orgEntities context, BaseTaskDataSource baseInfo)
        {
            switch (dataType.ToLower())
            {
                case "rolemember": return GetRoleMember(dataGuid, context);
                case "roleauthority": return GetRoleAuthority(dataGuid, context);
                case "rolelist": return GetRoleList(dataGuid, context);
                default: throw new Exception("RoleDS无法处理该" + dataType + "的数据");
            }
        }

        private static System.Xml.XmlNode GetRoleMember(string dataGuid, orgEntities context)
        {
            try
            {
                var result = XmlNodeManage.GetDocumentNode(Utility.GetTaskGuid(), dataGuid, "RoleMember");
                var role = context.Role.FirstOrDefault(cc => cc.Guid == dataGuid) ?? new Role
                                                                                         {
                                                                                             Guid = string.Empty,
                                                                                             Name = string.Empty,
                                                                                             PlatGuid = string.Empty,
                                                                                             PlatName = string.Empty,
                                                                                             AppGuid = string.Empty,
                                                                                             AppName = string.Empty,
                                                                                             Description = string.Empty,
                                                                                             AvailablePeriod = null,
                                                                                             Status = string.Empty,
                                                                                             Sort = null
                                                                                         };
                XmlNodeManage.SetSubValue(result, "Guid", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), Utility.CheckValue(role.Guid));
                XmlNodeManage.SetSubValue(result, "Name", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), Utility.CheckValue(role.Name));
                XmlNodeManage.SetSubValue(result, "PlatGuid", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), Utility.CheckValue(role.PlatGuid));
                XmlNodeManage.SetSubValue(result, "PlatName", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), Utility.CheckValue(role.PlatName));
                XmlNodeManage.SetSubValue(result, "AppGuid", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), Utility.CheckValue(role.AppGuid));
                XmlNodeManage.SetSubValue(result, "AppName", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), Utility.CheckValue(role.AppName));
                XmlNodeManage.SetSubValue(result, "Description", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), Utility.CheckValue(role.Description));
                XmlNodeManage.SetSubValue(result, "AvailablePeriod", Enum.GetName(typeof(TypeEnum), TypeEnum.DATA), Utility.CheckValue(role.AvailablePeriod));
                XmlNodeManage.SetSubValue(result, "Status", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), Utility.CheckValue(role.Status));
                XmlNodeManage.SetSubValue(result, "Order", Enum.GetName(typeof(TypeEnum), TypeEnum.LONG), Utility.CheckValue(role.Sort));
                var memberNode = XmlNodeManage.CreateNode("ListOUDataInfo");
                var cloneList = (IEnumerable<Branch>)context.Branch.ToArray().Clone();
                foreach (var member in role.RoleMember)
                {
                    var ouNode = XmlNodeManage.CreateNode("OUDataInfo");
// ReSharper disable AccessToModifiedClosure
                    var memberInfo = context.Member.FirstOrDefault(cc => cc.Guid == member.MemberId);
// ReSharper restore AccessToModifiedClosure
                    if (null == memberInfo)
                        continue;
                    XmlNodeManage.SetSubValue(ouNode, "@GUID", member.Guid);
                    XmlNodeManage.SetSubValue(ouNode, "@NAME", memberInfo.Name);
                    XmlNodeManage.SetSubValue(ouNode, "@OUType", "Member");
                    XmlNodeManage.SetSubValue(ouNode, "@CompanyGuid", Utility.GetCompanyGuid(memberInfo.BranchGuid, cloneList));
                    memberNode.AppendChild(ouNode);
                }
                result.AppendChild(memberNode);
                return result;
            }
            catch
            {
                throw new Exception("获取数据标识为：" + dataGuid + "的RoleMember数据时出错！");
            }
        }
        private static System.Xml.XmlNode GetRoleAuthority(string dataGuid, orgEntities context)
        {
            try
            {
                var result = XmlNodeManage.GetDocumentNode(Utility.GetTaskGuid(), dataGuid, "RoleAuthority");
                var role = context.Role.FirstOrDefault(cc => cc.Guid == dataGuid) ?? new Role
                                                                                         {
                                                                                             Guid = string.Empty,
                                                                                             Name = string.Empty,
                                                                                             PlatGuid = string.Empty,
                                                                                             PlatName = string.Empty,
                                                                                             AppGuid = string.Empty,
                                                                                             AppName = string.Empty,
                                                                                             Description = string.Empty,
                                                                                             ListAuthority = string.Empty,
                                                                                             Sort = null
                                                                                         };
                XmlNodeManage.SetSubValue(result, "Guid", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), role.Guid);
                XmlNodeManage.SetSubValue(result, "Name", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), role.Name);
                XmlNodeManage.SetSubValue(result, "PlatGuid", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), role.PlatGuid);
                XmlNodeManage.SetSubValue(result, "PlatName", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), role.PlatName);
                XmlNodeManage.SetSubValue(result, "AppGuid", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), role.AppGuid);
                XmlNodeManage.SetSubValue(result, "AppName", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), role.AppName);
                XmlNodeManage.SetSubValue(result, "Description", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), role.Description);
                XmlNodeManage.SetSubValue(result, "Order", Enum.GetName(typeof(TypeEnum), TypeEnum.LONG), role.Sort);
                var authorityNode = XmlNodeManage.CreateNode("ListAuthority");
                authorityNode.InnerXml = role.ListAuthority ?? string.Empty;
                result.AppendChild(authorityNode);
                return result;
            }
            catch
            {
                throw new Exception("获取RoleAuthority数据时出错！");
            }
        }
        private static System.Xml.XmlNode GetRoleList(string dataGuid, orgEntities context)
        {
            try
            {
                var result = XmlNodeManage.GetDocumentNode(Utility.GetTaskGuid(), dataGuid, "RoleList");
                var cloneList = (IEnumerable<Branch>)context.Branch.ToArray().Clone();
                var roleList = context.Role.Where(cc => cc.AppGuid == dataGuid).ToArray();
                context.Connection.Close();
                foreach (var role in roleList)
                {
                    var roleNode = XmlNodeManage.CreateNode("Role");
                    XmlNodeManage.SetSubValue(roleNode, "Guid", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), Utility.CheckValue(role.Guid));
                    XmlNodeManage.SetSubValue(roleNode, "Name", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), Utility.CheckValue(role.Name));
                    XmlNodeManage.SetSubValue(roleNode, "PlatGuid", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), Utility.CheckValue(role.PlatGuid));
                    XmlNodeManage.SetSubValue(roleNode, "PlatName", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), Utility.CheckValue(role.PlatName));
                    XmlNodeManage.SetSubValue(roleNode, "AppGuid", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), Utility.CheckValue(role.AppGuid));
                    XmlNodeManage.SetSubValue(roleNode, "AppName", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), Utility.CheckValue(role.AppName));
                    XmlNodeManage.SetSubValue(roleNode, "Description", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), Utility.CheckValue(role.Description));
                    XmlNodeManage.SetSubValue(roleNode, "AvailablePeriod", Enum.GetName(typeof(TypeEnum), TypeEnum.DATA), Utility.CheckValue(role.AvailablePeriod));
                    XmlNodeManage.SetSubValue(roleNode, "Status", Enum.GetName(typeof(TypeEnum), TypeEnum.TEXT), Utility.CheckValue(role.Status));
                    XmlNodeManage.SetSubValue(roleNode, "Order", Enum.GetName(typeof(TypeEnum), TypeEnum.LONG), Utility.CheckValue(role.Sort));
                    var memberNode = XmlNodeManage.CreateNode("ListOUDataInfo");
                    foreach (var member in role.RoleMember)
                    {
                        var ouNode = XmlNodeManage.CreateNode("OUDataInfo");
// ReSharper disable AccessToModifiedClosure
                        var memberInfo = context.Member.FirstOrDefault(cc => cc.Guid == member.MemberId);
// ReSharper restore AccessToModifiedClosure
                        if (null == memberInfo)
                            continue;
                        XmlNodeManage.SetSubValue(ouNode, "@GUID", Utility.CheckValue(member.Guid));
                        XmlNodeManage.SetSubValue(ouNode, "@NAME", Utility.CheckValue(memberInfo.Name));
                        XmlNodeManage.SetSubValue(ouNode, "@OUType", "Member");
                        XmlNodeManage.SetSubValue(ouNode, "@CompanyGuid", Utility.CheckValue(Utility.GetCompanyGuid(memberInfo.BranchGuid, cloneList)));
                        memberNode.AppendChild(ouNode);
                    }
                    var authorityNode = XmlNodeManage.CreateNode("ListAuthority");
                    authorityNode.InnerXml = role.ListAuthority ?? string.Empty;
                    roleNode.AppendChild(authorityNode);
                    roleNode.AppendChild(memberNode);
                    result.AppendChild(roleNode);
                }
                return result;
            }
            catch
            {
                throw new Exception("获取RoleList数据时出错！");
            }
        }
        #endregion
        #region\\set
        public int SetTaskData(OUDataInfo userInfo, string dataGuid, string dataType, System.Xml.XmlNode xmlData, orgEntities context)
        {
            var datatype = XmlNodeManage.GetSubValue(xmlData, "@DataType");
            switch (datatype.ToLower())
            {
                case "rolemember": return SetRoleMember(xmlData, context);
                case "roleauthority": return SetRoleAuthority(xmlData, context);
                default: throw new Exception("CompanyTask无法处理该" + datatype + "的数据");
            }
        }

        #region rolemember
        private static int SetRoleMember(System.Xml.XmlNode xmlData, orgEntities context)
        {
            System.Data.Common.DbTransaction tran = null;
            try
            {
                context.Connection.Open();
                tran = context.Connection.BeginTransaction();
                #region 更新Role数据
                var id = Utility.CheckXmlData(xmlData,"Guid");
                var role = context.Role.FirstOrDefault(cc => cc.Guid == id);
                if (role == null)
                {
                    role = new Role
                               {
                        Guid = Utility.CheckXmlData(xmlData,"Guid"),
                        Name = Utility.CheckXmlData(xmlData,"Name"),
                        PlatGuid = Utility.CheckXmlData(xmlData,"PlatGuid"),
                        PlatName = Utility.CheckXmlData(xmlData,"PlatName"),
                        AppGuid = Utility.CheckXmlData(xmlData,"AppGuid"),
                        AppName = Utility.CheckXmlData(xmlData,"AppName"),
                        AvailablePeriod = Convert.ToDateTime(Utility.CheckXmlData(xmlData,"AvailablePeriod")),
                        Description = Utility.CheckXmlData(xmlData,"Description"),
                        Status = Utility.CheckXmlData(xmlData,"Status"),
                        Sort = Convert.ToInt32(Utility.CheckXmlData(xmlData,"Order"))
                    };
                    context.AddToRole(role);
                }
                else
                {
                    role.Name = Utility.CheckXmlData(xmlData,"Name");
                    role.PlatGuid = Utility.CheckXmlData(xmlData,"PlatGuid");
                    role.PlatName = Utility.CheckXmlData(xmlData,"PlatName");
                    role.AppGuid = Utility.CheckXmlData(xmlData,"AppGuid");
                    role.AppName = Utility.CheckXmlData(xmlData,"AppName");
                    role.AvailablePeriod = Convert.ToDateTime(Utility.CheckXmlData(xmlData,"AvailablePeriod"));
                    role.Description = Utility.CheckXmlData(xmlData,"Description");
                    role.Status = Utility.CheckXmlData(xmlData,"Status");
                    role.Sort = Convert.ToInt32(Utility.CheckXmlData(xmlData,"Order"));
                }
                context.SaveChanges();
                #endregion
                #region 更新Member数据

                if (role.RoleMember.Count != 0)
                {
                    var memberList = role.RoleMember.ToList();
                    foreach (var t in memberList)
                        context.RoleMember.DeleteObject(t);
                }
                const string queryStr = "ListOUDataInfo/OUDataInfo";
                var temp = xmlData.SelectNodes(queryStr) ?? xmlData.SelectNodes(queryStr.ToLower());
                foreach (System.Xml.XmlNode item in temp)
                {
                    var ouGuid = item.Attributes["GUID"].Value;
                    var ouType = item.Attributes["OUType"].Value;
                    switch (ouType)
                    {
                        case "Member":
                            SetMember(id, ouGuid, context);
                            break;
                        case "Company":
                            SetCompany(id, ouGuid, context);
                            break;
                        case "Branch":
                            SetBranch(id, ouGuid, context);
                            break;
                        default: break;
                    }
                }
                #endregion

                context.SaveChanges();
                tran.Commit();
                return 0;
            }
            catch (Exception ex)
            {
                if (tran != null)
                    tran.Rollback();
                throw ex.InnerException;
            }
            finally
            {
                if (context != null && context.Connection.State != System.Data.ConnectionState.Closed)
                    context.Connection.Close();
            }
        }

        /// <summary>
        /// 根据单笔Member，写入RoleMember
        /// </summary>
        /// <param name="roleId">Role表的GUID</param>
        /// <param name="ouGuid">人员标识</param>
        /// <param name="context"></param>
        /// <returns></returns>
        private static void SetMember(string roleId, string ouGuid, orgEntities context)
        {
            var rolemember = context.RoleMember.FirstOrDefault(cc => cc.Guid == roleId && cc.MemberId == ouGuid);
            if (rolemember != null) return;
            var rolememberSave = new RoleMember
                                     {
                                         Guid = Guid.NewGuid().ToString(),
                                         RoleId = roleId,
                                         MemberId = ouGuid
                                     };
            context.AddToRoleMember(rolememberSave);
            context.SaveChanges();
        }

        /// <summary>
        /// 当OUType为Branch时，查找出所有所属人员，写入RoleMember
        /// </summary>
        /// <param name="roleId">Role的标识</param>
        /// <param name="branchGuid">部门标识</param>
        /// <param name="context"></param>
        private static void SetBranch(string roleId, string branchGuid, orgEntities context)
        {
            var member = (IEnumerable<Member>)context.Member.ToArray().Clone();
            var memberList = member.Where(cc => cc.BranchGuid == branchGuid);
            var rolemember = (IEnumerable<RoleMember>)context.RoleMember.ToArray().Clone();
            foreach (var item in memberList)
            {
// ReSharper disable AccessToModifiedClosure
                var rolememberSave = rolemember.FirstOrDefault(cc => cc.Guid == roleId && cc.MemberId == item.Guid);
// ReSharper restore AccessToModifiedClosure
                if (rolememberSave == null)
                {
                    var rolmemberadd = new RoleMember
                                           {
                        Guid = Guid.NewGuid().ToString(),
                        RoleId = roleId,
                        MemberId = item.Guid
                    };
                    context.AddToRoleMember(rolmemberadd);
                    context.SaveChanges();
                }
            }
        }

        /// <summary>
        /// 根据单位标识，找出单位事务处理人的标识，写入RoleMember
        /// </summary>
        /// <param name="roleId"></param>
        /// <param name="companyGuid"></param>
        /// <param name="context"></param>
        private static void SetCompany(string roleId, string companyGuid, orgEntities context)
        {
            var company = context.Company.FirstOrDefault(cc => cc.Guid == companyGuid);
            if (company != null)
            {
                SetMember(roleId, company.EventerGuid, context);
            }
        }
        #endregion

        #region roleauthority
        private static int SetRoleAuthority(System.Xml.XmlNode xmlData, orgEntities context)
        {
            try
            {
                var id = Utility.CheckXmlData(xmlData,"Guid");
                var role = context.Role.FirstOrDefault(cc => cc.Guid == id);
                var authorityNode = Utility.CheckXmlData(xmlData, "ListAuthority");
                if (role == null)
                {
                    role = new Role
                               {
                        Guid = Utility.CheckXmlData(xmlData,"Guid"),
                        Name = Utility.CheckXmlData(xmlData,"Name"),
                        PlatGuid = Utility.CheckXmlData(xmlData,"PlatGuid"),
                        PlatName = Utility.CheckXmlData(xmlData,"PlatName"),
                        AppGuid = Utility.CheckXmlData(xmlData,"AppGuid"),
                        AppName = Utility.CheckXmlData(xmlData,"AppName"),
                        Description = Utility.CheckXmlData(xmlData,"Description"),
                        ListAuthority= authorityNode,
                        Sort = Convert.ToInt32(Utility.CheckXmlData(xmlData,"Order"))
                    };
                    context.AddToRole(role);
                }
                else
                {
                    role.Name = Utility.CheckXmlData(xmlData,"Name");
                    role.PlatGuid = Utility.CheckXmlData(xmlData,"PlatGuid");
                    role.PlatName = Utility.CheckXmlData(xmlData,"PlatName");
                    role.AppGuid = Utility.CheckXmlData(xmlData,"AppGuid");
                    role.AppName = Utility.CheckXmlData(xmlData,"AppName");
                    role.Description = Utility.CheckXmlData(xmlData,"Description");
                    role.ListAuthority = authorityNode;
                    role.Sort = Convert.ToInt32(Utility.CheckXmlData(xmlData,"Order"));
                }
                var resultSave = context.SaveChanges();
                var result = resultSave == 1 ? 0 : 1;
                return result;

            }
            catch (Exception ex)
            {
                throw ex.InnerException;
            }
        }
        #endregion

        #endregion
        #region\\transform
        public System.Xml.XmlNode TransformTaskData(OUDataInfo userInfo, System.Xml.XmlNode xmlParam, orgEntities context, BaseTaskDataSource baseInfo)
        {
            throw new NotImplementedException();
        }
        #endregion
    }
}
